/**
 * 
 */
package controllers;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.http.HttpServletRequest;

import models.UploadFormModel;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.DefaultMultipartHttpServletRequest;

/**
 * @author hoannguyen
 * 
 * This class is used for processing for files uploading.
 */
@Controller
@RequestMapping("uploadfiles")
public class UploadFilesController {
	
	/**
	 * Constants
	 */
	private static final String UPLOAD_FILES = "upload-files";
	private static final String UPLOAD_FORM_MODEL = "uploadFormModel";
	private static final String UPLOAD_SUCCESSFULLY = "upload-successfully";
	
	/**
	 * The uploaded file's percent
	 */
	private float uploadPercent = 0;

	/**
	 * For logging
	 */
	private static final Log LOG = LogFactory.getLog(UploadFilesController.class);
	
	/**
	 * To process the first time the JSP file is loaded.
	 * @param map
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(method = RequestMethod.GET)
	public String loadForm(Map map) {
		
		// Log
		if (LOG.isDebugEnabled()) {
			LOG.debug("loadForm:");
		}
		
		// Add a uploadFormModel before rendering the JSP file
		map.put(UPLOAD_FORM_MODEL, new UploadFormModel());
		
		return UPLOAD_FILES;
	}
	
	/**
	 * To process when 01 file was uploaded.
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@SuppressWarnings({ "unchecked", "rawtypes" })
	@RequestMapping(method = RequestMethod.POST)
	public String upload(HttpServletRequest request) throws Exception {
		
		// Log
		if (LOG.isDebugEnabled()) {
			LOG.debug("upload:");
		}
		
		// Get multi-parts request
		DefaultMultipartHttpServletRequest fileReq = (DefaultMultipartHttpServletRequest) request;
		Map fileMap = fileReq.getMultiFileMap();
		Set<String> keySet = fileMap.keySet();
		for (String key : keySet) {
			List<MultipartFile> files = (List<MultipartFile>) fileMap.get(key); 
			for (MultipartFile file : files) {
				if (file.getSize() > 0) {

					// Build saved file name location
					String serverFileName = "D:/" + file.getOriginalFilename();

					// Get output stream for saving the files
					OutputStream os = new FileOutputStream(serverFileName);

					// Get input stream and write data to the output stream
					InputStream is = file.getInputStream();
					uploadPercent = 0;
					float uploadedSize = 0;
					int readBytes = 0;
					byte[] buffer = new byte[10000];
					while ((readBytes = is.read(buffer)) != -1) {
						os.write(buffer, 0, readBytes);
						uploadedSize += readBytes;
						uploadPercent =  Math.round(uploadedSize / file.getSize() * 100);
						LOG.debug("Percentttttttttttttttttttttt:" + uploadPercent);
					}

					// Close streams
					is.close();
					os.close();
				}
			}
		}

		return UPLOAD_SUCCESSFULLY;
	}
	
	/**
	 * To delete a file with the given file name
	 * @param request
	 * @param fileName
	 */
	@RequestMapping(value="/deletefile", method = RequestMethod.POST)
	public void deleteUploadedFile(HttpServletRequest request, @RequestBody String fileName){
		File file = new File("D:/" + fileName);
		file.delete();
	}
	
	/**
	 * To process when users confirm the uploaded files.
	 * @param request
	 * @param map
	 * @return
	 */
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value="/confirm", method = RequestMethod.POST)
	public String confirmUploadedFiles(HttpServletRequest request, Map map){
		
		// Get file name array
		String[] fileNames = request.getParameterValues("hdFileName");
		
		// File name list		
		List<String> notEmptyNameList = new ArrayList<String>();
		
		if (fileNames != null) {

			// Convert the  file name array to the file  name  list and remove empty file name string ""
			notEmptyNameList = new LinkedList<String>(Arrays.asList(fileNames));
			for (int i = 0; i < notEmptyNameList.size(); i++) {
				String fileName = notEmptyNameList.get(i);
				if (fileName.trim().equals("")) {
					notEmptyNameList.remove(i);
					i--;
				}
			}
		}
		// Convert the file name list back to the string array
		String[] notEmptyNames = notEmptyNameList.toArray(new String[notEmptyNameList.size()]); 
		map.put("fileNames", notEmptyNames);
		
		return UPLOAD_SUCCESSFULLY;
	}
}
